

import { MessageService } from './models/Message';
import { LiveStreamMessage, isWebcastGiftMessage, isWebcastRoomStatsMessage, WebcastRoomStatsMessage, isWebcastRoomRankMessage, isWebcastRoomUserSeqMessage } from './types/MessageTypes';
import UserRoomGift from './models/sequelize/UserRoomGift';
import { StatisticService } from './models/StatisticService';
import { GiftService } from './models/Gift';
import type { WebcastChatMessage, WebcastGiftMessage } from './types/MessageTypes';
import { UserSnapshotService, UserSnapshotData } from './models/UserSnapshot';
import * as fs from 'fs';
import * as path from 'path';
import dotenv from 'dotenv';

// 加载环境变量（如果其他模块已加载，这里重复调用也不会有副作用）
dotenv.config();

// 简单的环境变量读取辅助
const envInt = (key: string, def: number) => {
  const raw = process.env[key];
  if (raw === undefined || raw === null) return def;
  const n = parseInt(String(raw), 10);
  return Number.isFinite(n) && n >= 0 ? n : def;
};
import { puppeteerManager } from './puppeteer-service';
import { LiveSessionService } from './models/LiveSession';
import { ensureUserId } from './utils/anonymousUser';
import { RoomService } from './models/Room';
import Room from './models/sequelize/Room';
/**
 * LiveStreamManager - 直播流管理器
 *
 * sessionBook 设计逻辑：
 * - sessionBook 中有 session → 说明正在进行弹幕录制
 * - session.isRecording === true → 说明正在进行视频录制（同时必然也在弹幕录制）
 *
 * 关系：
 * - 视频录制 → 必然有弹幕录制
 * - 弹幕录制 → 不一定有视频录制
 */
export class LiveStreamManager {
  private static   messageService = new MessageService();
  private static statisticService = new StatisticService();
  private static giftService = new GiftService();
  private static  userSnapshotService = new UserSnapshotService();
  private static roomService = new RoomService();

  // 全局book缓存：roomId -> 状态（包含 sessionId 与是否录制）
  private static sessionBook = new Map<string, { sessionId: string; isRecording?: boolean; lastSeenAt: number; startedAt: number }>();
  private static readonly URL_CONFIG_PATH = path.join(process.cwd(), '..', 'DouyinLiveRecorder', 'config', 'URL_config.ini');

  // 轮询相关配置（支持通过 .env 覆盖）
  private static readonly POLLING_INTERVAL = envInt('polling_interval_minutes', 10) * 60 * 1000; // 默认10分钟
  private static readonly REST_INTERVAL = envInt('rest_interval_minutes', 10) * 60 * 1000; // 默认10分钟
  private static readonly MAX_CONCURRENT_RECORDINGS = envInt('max_record_count', 10); // 默认10个并发录制
  private static pollingTimer: NodeJS.Timeout | null = null;
  private static isPollingEnabled = false;

  // 请求均摊相关
  private static roomCheckQueue: string[] = []; // 待检查的房间队列
  private static currentCheckIndex = 0; // 当前检查索引
  private static checkTimer: NodeJS.Timeout | null = null; // 单个房间检查定时器

  // 【新增】请求频率控制
  private static requestTimestamps = new Map<string, number>(); // roomId -> 上次请求时间戳
  private static readonly MIN_REQUEST_INTERVAL = envInt('min_request_interval_seconds', 30) * 1000; // 最小请求间隔，默认30秒

  // 【新增】直播间信息缓存
  private static liveInfoCache = new Map<string, {
    info: any; // DyLiveInfo
    timestamp: number;
  }>();
  private static readonly CACHE_TTL = envInt('cache_ttl_seconds', 60) * 1000; // 缓存有效期，默认60秒

  // URL_config.ini 操作辅助函数
  private static ensureFileExists(filePath: string) {
    const dir = path.dirname(filePath);
    if (!fs.existsSync(dir)) {
      fs.mkdirSync(dir, { recursive: true });
    }
    if (!fs.existsSync(filePath)) {
      fs.writeFileSync(filePath, '', { encoding: 'utf8' });
    }
  }

  private static readLines(filePath: string): string[] {
    this.ensureFileExists(filePath);
    const txt = fs.readFileSync(filePath, 'utf8');
    if (!txt) return [];
    return txt.split(/\r?\n/);
  }

  private static writeLines(filePath: string, lines: string[]) {
    const content = lines.join('\r\n');
    fs.writeFileSync(filePath, content, { encoding: 'utf8' });
  }

  private static extractRoomIdFromLine(line: string): string | null {
    const trimmed = line.trim();
    if (!trimmed) return null;
    const uncommented = trimmed.startsWith('#') ? trimmed.slice(1).trimStart() : trimmed;
    const urlPart = uncommented.split(/[,\uFF0C]/, 1)[0];
    const urlSegment = urlPart.trim();
    if (!urlSegment) return null;
    const match = urlSegment.match(/https?:\/\/live\.douyin\.com\/([^\s#,?]+)/i);
    return match ? match[1] : null;
  }


  private static makeUrl(roomId: string) {
    return `https://live.douyin.com/${roomId}`;
  }

  // 清空 URL_config.ini（在服务器启动时调用）
  static clearUrlConfig() {
    try {
      this.ensureFileExists(this.URL_CONFIG_PATH);
      this.writeLines(this.URL_CONFIG_PATH, []);
      console.log('🔧 已清空 URL_config.ini');
    } catch (error) {
      console.error('清空 URL_config.ini 失败:', error);
    }
  }

  // 设置房间的sessionId（若不存在则创建，保留 isRecording 状态）
  static setRoomSession(roomId: string, sessionId: string) {
    const now = Date.now();
    const prev = this.sessionBook.get(roomId);
    this.sessionBook.set(roomId, {
      sessionId,
      isRecording: prev?.isRecording ?? false,
      lastSeenAt: now,
      startedAt: prev?.startedAt ?? now,
    });
    console.log(`📖 设置房间session缓存: ${roomId} -> ${sessionId}`);
  }

  // 标记弹幕录制开始/停止（仅更新sessionBook状态，不设置isRecording）
  static async startDanmuRecording(roomId: string) {
    let s = this.sessionBook.get(roomId);
    if(!s){
      const liveInfo = await puppeteerManager.getLiveInfo(roomId);
      if (liveInfo?.status !== 2) {
        console.log(`⚠️ 房间 ${roomId} 当前非直播状态(status=${liveInfo?.status ?? 'unknown'})，跳过录制`);
        return;
      }

      try {
        // ✅ 步骤1: 先创建 session（确保数据库记录存在）
        console.log(`📝 [弹幕] 为房间 ${roomId} 创建或获取 session...`);
        const liveSessionService = new LiveSessionService();
        const sessionId = await liveSessionService.getOrCreateCurrentSession(roomId, liveInfo.title);
        console.log(`✅ [弹幕] Session 已就绪: ${sessionId}`);

        // ✅ 步骤2: 将 sessionId 存入 sessionBook（在连接前设置）
        // 这样即使 WebSocket 立即收到消息，handleMessage() 也能找到 sessionId
        this.sessionBook.set(roomId, {
          sessionId: sessionId,
          isRecording: false, // 单独连接弹幕，不录制视频
          lastSeenAt: Date.now(),
          startedAt: Date.now(),
        });
        console.log(`📖 [弹幕] SessionBook 已设置: ${roomId} -> ${sessionId}`);

        // ✅ 步骤3: 最后才建立 WebSocket 连接（此时 session 和 sessionBook 都已就绪）
        console.log(`🔗 [弹幕] 开始连接房间 ${roomId}...`);
        const result = await puppeteerManager.connectLiveRoom(roomId);

        if (!result.success) {
          console.error(`❌ [弹幕] 连接房间 ${roomId} 失败: ${result.message}，清理 sessionBook`);
          this.sessionBook.delete(roomId);  // 连接失败，清理 sessionBook
          return;
        }

        console.log(`✅ [弹幕] 连接房间 ${roomId} 成功，可以开始接收消息`);
        s = this.sessionBook.get(roomId);
      } catch (error) {
        console.error(`❌ [弹幕] 连接房间 ${roomId} 异常:`, error);
        // 清理可能已设置的 sessionBook 条目
        this.sessionBook.delete(roomId);
        return;
      }
    }

    // 只更新 lastSeenAt，不修改 isRecording 状态
    if (s) { s.lastSeenAt = Date.now(); }
  }
  static stopDanmuRecording(roomId: string) {
    const s = this.sessionBook.get(roomId);
    if (s) { s.isRecording = false; s.lastSeenAt = Date.now(); }
  }

  // 标记视频录制开始/停止
  static async startVideoRecording(roomId: string) {
    // 先确保弹幕录制已启动（确保 session 存在）
    await this.startDanmuRecording(roomId);

    // 然后设置为视频录制状态
    const s = this.sessionBook.get(roomId);
    if (s) {
      s.isRecording = true;
      s.lastSeenAt = Date.now();
    }

    // 写入 URL_config.ini
    try {
      const lines = this.readLines(this.URL_CONFIG_PATH);
      const url = this.makeUrl(roomId);

      // 检查是否已存在该roomId的URL
      const existingIndex = lines.findIndex(line => {
        const id = this.extractRoomIdFromLine(line);
        return id === roomId;
      });

      if (existingIndex === -1) {
        // 不存在则添加
        lines.push(url);
        this.writeLines(this.URL_CONFIG_PATH, lines);
      }
    } catch (error) {
      console.error(`启动视频录制时操作URL_config.ini失败: ${error}`);
    }
  }

  static stopVideoRecording(roomId: string) {
    const s = this.sessionBook.get(roomId);
    if (s) {
      s.isRecording = false;
      s.lastSeenAt = Date.now();
    }

    // 重新写入 URL_config.ini
    try {
      const lines = this.readLines(this.URL_CONFIG_PATH);

      // 过滤掉该roomId的所有行
      const filteredLines = lines.filter(line => {
        const id = this.extractRoomIdFromLine(line);
        return id !== roomId;
      });

      this.writeLines(this.URL_CONFIG_PATH, filteredLines);
    } catch (error) {
      console.error(`停止视频录制时操作URL_config.ini失败: ${error}`);
    }
  }

  // 获取房间的sessionId
  static getRoomSession(roomId: string): string | null {
    const s = this.sessionBook.get(roomId);
    return s?.sessionId || null;
  }

  // 续命（收到任何消息时调用）
  static bump(roomId: string) {
    const s = this.sessionBook.get(roomId);
    if (s) s.lastSeenAt = Date.now();
  }

  static async handleRoomDisconnected(roomId: string, payload?: { code?: number; reason?: string }) {
    console.log(`🔌 [断开] 处理房间 ${roomId} 断开连接 (code: ${payload?.code}, reason: ${payload?.reason})`);

    const entry = this.sessionBook.get(roomId);

    if (!entry) {
      console.log(`⚠️  [断开] 房间 ${roomId} 在 sessionBook 中未找到，可能已被清理或未成功建立连接`);
      return;
    }

    // 结束 LiveSession
    try {
      const liveSessionService = new LiveSessionService();
      await liveSessionService.endSession(entry.sessionId);
      console.log(`✅ [断开] 已结束 session ${entry.sessionId}`);
    } catch (error) {
      console.error(`❌ [断开] 更新 session ${entry.sessionId} 结束时间失败`, error);
    }

    // 清理录制状态和 sessionBook
    try {
      // 停止视频录制（如果正在录制）
      if (entry.isRecording) {
        this.stopVideoRecording(roomId);
        console.log(`✅ [断开] 已停止房间 ${roomId} 的视频录制`);
      }

      // 从 sessionBook 中删除
      this.sessionBook.delete(roomId);
      console.log(`✅ [断开] 已从 sessionBook 中删除房间 ${roomId}`);
    } catch (error) {
      console.error(`❌ [断开] 清理房间 ${roomId} 状态失败`, error);
    }
  }

  // 返回快照，包含 isRecording
  static snapshot() {
    return Array.from(this.sessionBook.entries()).map(([roomId, s]) => ({
      roomId,
      sessionId: s.sessionId,
      isRecording: s.isRecording === true,
      lastSeenAt: s.lastSeenAt,
      startedAt: s.startedAt,
    }));
  }

  static async handleMessage(messageData: LiveStreamMessage, roomId: string) {
    try {
      const sessionId = LiveStreamManager.getRoomSession(roomId);

      if (!sessionId) {
        console.error(`❌ 房间 ${roomId} 没有找到sessionId，跳过消息处理`);
        return;
      }

      if (isWebcastGiftMessage(messageData)) {
        await LiveStreamManager.handleGiftMessage(messageData, roomId, sessionId);
        return;
      }

      if (isWebcastRoomStatsMessage(messageData)) {
        await LiveStreamManager.handleStatsMessage(messageData, roomId, sessionId);
        return;
      }

      if (isWebcastRoomRankMessage(messageData) || isWebcastRoomUserSeqMessage(messageData)) {
        return;
      }

      await LiveStreamManager.messageService.saveMessage(messageData, roomId, sessionId);
    } catch (error) {
      console.error('处理直播消息失败:', error);
    }
  }

  static async handleGiftMessage(messageData: WebcastGiftMessage, roomId: string, sessionId: string) {
    try {
      const { user, gift } = messageData;

      // 确保用户有ID（匿名用户会生成虚拟ID）
      const userId = ensureUserId(user, roomId);

      // 先查找或创建礼物
      const giftRecord = await LiveStreamManager.giftService.getOrCreateGift({
        name: gift.name,
        price: gift.price || 0,
        type: gift.type,
        description: gift.desc,
        icon: gift.icon
      });

      // 创建或获取用户快照
      const userSnapshotData: UserSnapshotData = {
        userId: userId, // 使用确保后的userId
        userName: user.name,
        userAvatar: user.avatar,
        payGrade: user.payGrade?.level ? parseInt(user.payGrade.level) : null,
        fansLevel: user.fansClub?.data?.level || null,
        fansClubName: user.fansClub?.data?.anchorId || null,
        // 管理员权限字段
        isAdmin: user.isAdmin || false
      };

      const userSnapshotId = await LiveStreamManager.userSnapshotService.ensureUserSnapshot(
        userId, // 使用确保后的userId
        userSnapshotData,
        user.gender
      );

      // 使用upsert避免重复插入礼物记录
      const [userGiftRecord, created] = await UserRoomGift.upsert({
        id: messageData.id, // 使用消息ID作为主键
        userId: userId, // 使用确保后的userId（可能是真实ID或虚拟ID）
        roomId: roomId,
        giftId: giftRecord.id,
        quantity: parseInt(gift.count) || 1,
        sessionId: sessionId,
        userSnapshotId: userSnapshotId
      });

      // console.log('🎁 处理礼物消息: roomId=' + roomId + ', sessionId=' + sessionId + ', gift=' + giftRecord.name + ', user=' + user.name + ', quantity=' + gift.count);

    } catch (error) {
      console.error('❌ 保存礼物记录失败:', error);
    }
  }

  static async handleStatsMessage(messageData: WebcastRoomStatsMessage, roomId: string, sessionId: string) {
    try {
      const audienceCount = parseInt(messageData.room.audienceCount) || 0;
      // 保存统计数据到Statistic表
      await this.statisticService.saveStatistic(sessionId, audienceCount);

      // console.log(`📊 处理统计消息: roomId=${roomId}, sessionId=${sessionId}, audienceCount=${audienceCount}`);
    } catch (error) {
      console.error('❌ 处理统计消息失败:', error);
    }
  }

  // ==================== 轮询监听模块 ====================

  /**
   * 启动轮询监听模块
   */
  static startPolling() {
    if (this.isPollingEnabled) {
      console.log('⚠️ 轮询监听已经启动');
      return;
    }

    this.isPollingEnabled = true;
    console.log('🔄 启动轮询监听模块');
    
    // 立即执行一次轮询
    this.executePollingCycle();
  }

  /**
   * 停止轮询监听模块
   */
  static stopPolling() {
    if (!this.isPollingEnabled) {
      console.log('⚠️ 轮询监听未启动');
      return;
    }

    this.isPollingEnabled = false;
    console.log('⏹️ 停止轮询监听模块');

    // 清除定时器
    if (this.pollingTimer) {
      clearTimeout(this.pollingTimer); // 改为clearTimeout，因为现在使用setTimeout
      this.pollingTimer = null;
    }

    if (this.checkTimer) {
      clearTimeout(this.checkTimer);
      this.checkTimer = null;
    }

    // 清空队列
    this.roomCheckQueue = [];
    this.currentCheckIndex = 0;
  }

  /**
   * 执行一次完整的轮询周期
   */
  private static async executePollingCycle() {
    try {
      console.log('🔄 开始执行轮询周期');

      // 获取所有房间，按权重排序
      const rooms = await this.getAllRoomsSortedByWeight();
      
      if (rooms.length === 0) {
        console.log('📭 没有找到任何房间，跳过本次轮询');
        return;
      }

      console.log(`📋 找到 ${rooms.length} 个房间，开始分布式检查`);

      // 设置房间检查队列
      this.roomCheckQueue = rooms.map(room => room.id);
      this.currentCheckIndex = 0;

      // 开始分布式检查
      this.startDistributedCheck();

    } catch (error) {
      console.error('❌ 执行轮询周期失败:', error);
    }
  }

  /**
   * 获取所有房间，按权重排序
   */
  private static async getAllRoomsSortedByWeight(): Promise<Room[]> {
    try {
      const rooms = await Room.findAll({
        order: [
          ['weight', 'DESC'], // 权重高的优先
          ['createdAt', 'ASC'] // 权重相同时，创建时间早的优先
        ]
      });
      return rooms;
    } catch (error) {
      console.error('❌ 获取房间列表失败:', error);
      return [];
    }
  }

  /**
   * 开始分布式检查房间状态
   */
  private static startDistributedCheck() {
    if (!this.isPollingEnabled) {
      return;
    }

    if (this.roomCheckQueue.length === 0) {
      // 没有房间需要检查，直接安排下一轮轮询
      this.scheduleNextPollingCycle();
      return;
    }

    // 计算每个房间检查的间隔时间（10分钟内均匀分布）
    const totalRooms = this.roomCheckQueue.length;
    const checkInterval = Math.floor(this.POLLING_INTERVAL / totalRooms);
    
    console.log(`⏱️ 将在 ${this.POLLING_INTERVAL / 1000} 秒内检查 ${totalRooms} 个房间，每 ${checkInterval / 1000} 秒检查一个`);

    // 立即检查第一个房间
    this.checkNextRoom();

    // 设置定时器检查后续房间
    this.scheduleNextCheck(checkInterval);
  }

  /**
   * 安排下一次房间检查
   */
  private static scheduleNextCheck(interval: number) {
    if (!this.isPollingEnabled) {
      return;
    }

    this.checkTimer = setTimeout(() => {
      this.checkNextRoom();
      
      // 如果还有房间需要检查，继续安排下一次
      if (this.currentCheckIndex < this.roomCheckQueue.length) {
        this.scheduleNextCheck(interval);
      } else {
        // 一轮轮询完成，安排下一轮轮询（休息10分钟后）
        this.scheduleNextPollingCycle();
      }
    }, interval);
  }

  /**
   * 安排下一轮轮询周期（在休息间隔后）
   */
  private static scheduleNextPollingCycle() {
    if (!this.isPollingEnabled) {
      return;
    }

    console.log(`✅ 本轮轮询完成，将在 ${this.REST_INTERVAL / 1000} 秒后开始下一轮轮询`);
    
    this.pollingTimer = setTimeout(() => {
      if (this.isPollingEnabled) {
        this.executePollingCycle();
      }
    }, this.REST_INTERVAL);
  }

  /**
   * 检查下一个房间
   */
  private static async checkNextRoom() {
    if (!this.isPollingEnabled || this.currentCheckIndex >= this.roomCheckQueue.length) {
      return;
    }

    const roomId = this.roomCheckQueue[this.currentCheckIndex];
    this.currentCheckIndex++;

    try {
      await this.checkRoomStatus(roomId);
    } catch (error) {
      console.error(`❌ 检查房间 ${roomId} 状态失败:`, error);
    }
  }

  /**
   * 【新增】带缓存和频率控制的直播间信息获取
   * 防止频繁请求触发反爬虫
   */
  private static async getLiveInfoWithCache(roomId: string) {
    // 1. 检查缓存
    const cached = this.liveInfoCache.get(roomId);
    if (cached && Date.now() - cached.timestamp < this.CACHE_TTL) {
      console.log(`✅ [缓存] 使用缓存数据: ${roomId}`);
      return cached.info;
    }

    // 2. 检查请求频率
    const lastRequest = this.requestTimestamps.get(roomId) || 0;
    const elapsed = Date.now() - lastRequest;

    if (elapsed < this.MIN_REQUEST_INTERVAL) {
      const delay = this.MIN_REQUEST_INTERVAL - elapsed;
      console.log(`⏱️  [频控] 房间 ${roomId} 请求过快，等待 ${Math.round(delay / 1000)}秒`);
      await new Promise(resolve => setTimeout(resolve, delay));
    }

    // 3. 添加随机延迟（2-5秒，模拟人类行为）
    const randomDelay = Math.random() * 3000 + 2000;
    await new Promise(resolve => setTimeout(resolve, randomDelay));

    // 4. 执行请求
    this.requestTimestamps.set(roomId, Date.now());
    const liveInfo = await puppeteerManager.getLiveInfo(roomId);

    // 5. 更新缓存
    this.liveInfoCache.set(roomId, {
      info: liveInfo,
      timestamp: Date.now()
    });

    return liveInfo;
  }

  /**
   * 检查单个房间的直播状态并处理录制逻辑
   */
  private static async checkRoomStatus(roomId: string) {
    try {
      // 获取直播状态（使用带缓存和频率控制的方法）
      const liveInfo = await this.getLiveInfoWithCache(roomId);
      const isLive = liveInfo?.status === 2; // 2表示直播中
      
      // 获取当前录制状态
      const currentSession = this.sessionBook.get(roomId);
      const isCurrentlyRecording = currentSession?.isRecording === true;

      console.log(`🔍 检查房间 ${roomId}: 直播状态=${liveInfo?.status}, 当前录制=${isCurrentlyRecording}`);

      if (isLive && !isCurrentlyRecording) {
        // 主播开播且未录制 -> 尝试开始录制
        await this.handleStreamStart(roomId, liveInfo);
      } else if (!isLive && isCurrentlyRecording) {
        // 主播下播且正在录制 -> 结束录制
        await this.handleStreamEnd(roomId);
      }

    } catch (error) {
      console.error(`❌ 检查房间 ${roomId} 状态失败:`, error);
    }
  }

  /**
   * 处理主播开播
   */
  private static async handleStreamStart(roomId: string, liveInfo: any) {
    try {
      // 检查当前录制数量是否已达上限
      const currentRecordingCount = this.getCurrentRecordingCount();
      
      if (currentRecordingCount >= this.MAX_CONCURRENT_RECORDINGS) {
        // 已达上限，检查是否可以替换低权重的录制
        const canReplace = await this.tryReplaceLowestWeightRecording(roomId);
        if (!canReplace) {
          console.log(`⚠️ 房间 ${roomId} 开播，但录制数量已达上限且权重不足以替换现有录制`);
          return;
        }
      }

      // 开始录制
      console.log(`🎬 房间 ${roomId} 开播，开始录制 (${liveInfo.title || '无标题'})`);
      await this.startVideoRecording(roomId);
      
    } catch (error) {
      console.error(`❌ 处理房间 ${roomId} 开播失败:`, error);
    }
  }

  /**
   * 处理主播下播
   */
  private static async handleStreamEnd(roomId: string) {
    try {
      console.log(`📴 房间 ${roomId} 下播，结束录制`);
      await this.handleRoomDisconnected(roomId, { reason: '主播下播' });
    } catch (error) {
      console.error(`❌ 处理房间 ${roomId} 下播失败:`, error);
    }
  }

  /**
   * 获取当前录制数量
   */
  private static getCurrentRecordingCount(): number {
    let count = 0;
    for (const session of this.sessionBook.values()) {
      if (session.isRecording === true) {
        count++;
      }
    }
    return count;
  }

  /**
   * 尝试替换权重最低的录制
   */
  private static async tryReplaceLowestWeightRecording(newRoomId: string): Promise<boolean> {
    try {
      // 获取新房间的权重
      const newRoom = await Room.findByPk(newRoomId);
      const newWeight = newRoom?.weight || 0;

      // 找到当前录制中权重最低的房间
      let lowestWeight = Infinity;
      let lowestWeightRoomId: string | null = null;

      for (const [roomId, session] of this.sessionBook.entries()) {
        if (session.isRecording === true) {
          const room = await Room.findByPk(roomId);
          const weight = room?.weight || 0;
          
          if (weight < lowestWeight) {
            lowestWeight = weight;
            lowestWeightRoomId = roomId;
          }
        }
      }

      // 如果新房间权重更高，则替换
      if (lowestWeightRoomId && newWeight > lowestWeight) {
        console.log(`🔄 替换录制: 停止低权重房间 ${lowestWeightRoomId} (权重=${lowestWeight})，开始高权重房间 ${newRoomId} (权重=${newWeight})`);
        
        // 停止低权重房间的录制
        await this.handleRoomDisconnected(lowestWeightRoomId, { reason: '被高权重房间替换' });
        
        return true;
      }

      return false;
    } catch (error) {
      console.error('❌ 尝试替换录制失败:', error);
      return false;
    }
  }

  /**
   * 获取轮询状态信息
   */
  static getPollingStatus() {
    return {
      isEnabled: this.isPollingEnabled,
      currentRecordingCount: this.getCurrentRecordingCount(),
      maxRecordings: this.MAX_CONCURRENT_RECORDINGS,
      pollingInterval: this.POLLING_INTERVAL,
      restInterval: this.REST_INTERVAL,
      queueLength: this.roomCheckQueue.length,
      currentCheckIndex: this.currentCheckIndex,
      nextCheckIn: this.checkTimer ? 'scheduled' : 'none',
      nextPollingCycleIn: this.pollingTimer ? 'scheduled' : 'none'
    };
  }
}
